#include "codekata_foo.h"
#include "codekata_api.h"
#include <stdio.h>
#include <string.h>

#ifdef __cplusplus
extern "C" {
#endif


int innerHelloMsgProc(void *msgHdr, int msgLen) { return 0; }
int innerSubscribeMsgProc(void *msgHdr, int msgLen) { return 0; }
int innerPersonMsgProc(void *msgHdr, int msgLen)
{
    if (msgLen != sizeof(person)) {
        return -1;
    }
    person *p = (person *)msgHdr;
    printf("p name(%s) addr(%s) age(%d)\n", p->name, p->addr, p->age);
    return 0;
}
int innerParentsMsgProc(void *msgHdr, int msgLen) { return 0; }

typedef int (*innerMsgProcFunc)(void *msgHdr, int msgLen);

#define MAX_MSG_PROC_FUNC_NUMS 128
innerMsgProcFunc g_msgProcFuncTbl[MAX_MSG_PROC_FUNC_NUMS] = {0};

int installMsgProcFunc(E_msgType msgType, innerMsgProcFunc fn)
{
    if (msgType >= MAX_MSG_PROC_FUNC_NUMS) {
        return -1;
    }
    g_msgProcFuncTbl[msgType] = fn;
    return 0;
}

int innerMsgProcFuncInit()
{
    memset(g_msgProcFuncTbl, 0, sizeof(g_msgProcFuncTbl));
    installMsgProcFunc(eHelloMsg, innerHelloMsgProc);
    installMsgProcFunc(eSubscribeMsg, innerSubscribeMsgProc);
    installMsgProcFunc(ePersonMsg, innerPersonMsgProc);
    installMsgProcFunc(eParentsMsg, innerParentsMsgProc);
    return 0;
}

int innerMsgProcFuncGet(E_msgType msgType, innerMsgProcFunc *fn)
{
    if (msgType > MAX_MSG_PROC_FUNC_NUMS) {
        return -1;
    }
    *fn = g_msgProcFuncTbl[msgType];
    return 0;
}

// use send person msg
int MockFooSendPersonMsg()
{
    person john = {
        .name = "john",
        .addr = "New York",
        .age  = 19,
    };

    RawMsg msg  = {0};
    msg.msgHdr  = &john;
    msg.msgLen  = sizeof(person);
    msg.msgType = ePersonMsg;
    return FooSndMsg(&msg, sizeof(msg));
}

int MockFooAllMsgProc(void *msgHdr, int msgLen)
{

    if (msgLen != sizeof(RawMsg)) {
        return -1;
    }

    RawMsg          *raw     = (RawMsg *)msgHdr;
    E_msgType        msgType = raw->msgType;
    innerMsgProcFunc fn;
    int              ret = innerMsgProcFuncGet(msgType, &fn);
    if (ret != 0) {
        return -1;
    }
    printf("msg rcv type(%d) success!\n", raw->msgType);
    fn(raw->msgHdr, raw->msgLen);
    return 0;
}

int MockFooInit(){
    innerMsgProcFuncInit();
    FooRegMsgRcv(MockFooAllMsgProc);
    return 0;
}

#ifdef __cplusplus
}
#endif